# -*- coding: utf8 -*-

from plugmgr import plugin

__all__ = ["help"]

(
C_COMMAND,
C_CATEGORY
) = range(2)

class help(plugin):
    ''' This class implements help command '''
    requires = ['cmd','lang','config']
    def __init__(self, bot):
        self.bot = bot
        bot["lang"].add("help")
        bot["cmd"].addHandler("help", self.help)
    def unload(self):
        self.bot["lang"].remove("help")
        self.bot["cmd"].removeHandler("help")
    def parse(self,text):
        ''' Parse __doc__ contents '''
        # TODO: сохранить отступы относительно друг друга
        if text is None: text = ''
        text = text.strip().split('\n')
        if len(text) and len(text[0]) and text[0][0]=='@':
            category = text[0][1:]
            text = '\n'.join(i.strip() for i in text[1:])
        else:
            category = 'misc' # TODO: возможно, лучше заменить это названием плагина, содержащего сию команду
            text = '\n'.join(i.strip() for i in text)
        return map(lambda x: x.strip(),category.split(',')), text
    def seek(self):
        # TODO: может, какое кэширование добавить?
        ch = self.bot['cmd'].cmdHandlers
        cc = {}
        for i in ch.keys():
            for j in self.parse(ch[i][0].__doc__)[0]:
                try:             cc[j].append(i)
                except KeyError: cc[j] = [i]
        return cc
    def determinate(self,s):
        ''' Tries to find s in commands and categories list '''
        r = []
        if s in self.bot['cmd'].cmdHandlers.keys(): r.append(C_COMMAND)
        if s in self.seek().keys()+['*']:           r.append(C_CATEGORY)
        return r
    def help(self, c):
        ''' Show help or list of categories if command or category is unknown. You can use * if you want to see all the commands. '''
        # developers note: для помещения команды в конкретную категорию установите первой строку вида
        # @cat
        # где cat — название соответствующей категории. категорий может быть несколько (разделяйте их запятыми)
        # описание категории ищется в переводах. если категория не найдена, используется misc.
        # для перевода непосредственно справки ищется идентификатор без указателя на категорию
        # вы можете использовать значения строк документации, используя строку вида '%ключ%'
        try:    arg = c.args.strip()
        except: arg = None # no command provided
        type = self.determinate(arg)
        if len(type)==2:
            text = c._('There is command and category with the same names. Please tell developers of both things to eliminate collision.')
        elif C_COMMAND in type:
            # покажем справку по команде
            text = self.bot['cmd'].cmdHandlers[arg][0].__doc__
            cat, text = self.parse(text)
            if not text: text = 'No help provided'
            # use translations for documentation provided by 3rdparty commands.
            # if there is no translation, use the default value.
            text = c._(text)
            for i in self.bot['config'].keys(1000): # если ключ из конфига упомянут в справке, то его явно надо показать, isn't it?
                text = text.replace('%%%s%%'%i,self.bot["config"][i])
        elif C_CATEGORY in type:
            # выдираем список команд в категории и фильтруем его по уровню доступа
            if arg=='*':
                commands = self.bot['cmd'].cmdHandlers.keys()
            else:
                # try-except не нужен, ибо мы и так знаем, что это категория, и она существует :)
                commands = self.seek()[arg]
            commands = filter(lambda x: self.bot['cmd'].cmdHandlers[x][1]<=c.access(),commands)
            commands.sort()
            text = c._('Available commands: %s')%(', '.join(commands or c._('No commands available for you')))
        else:
            categories = self.seek().keys()
            categories.sort()
            text = c._('Available categories: %s')%(', '.join(categories))
        c.reply(text)

